package com.lemon.exam.common.converter;

import com.lemon.exam.entity.vo.PaperVO;
import io.r2dbc.spi.Row;
import io.r2dbc.spi.RowMetadata;
import org.apache.commons.lang3.tuple.Triple;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.convert.ReadingConverter;
import org.springframework.lang.NonNull;

import java.time.LocalDateTime;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;

/**
 * 试卷对象转换器
 *
 * @author Lemon
 * @since 2025/7/3 16:51
 */
@ReadingConverter
public class PaperConverter implements Converter<Row, PaperVO> {
    /**
     * 映射关系
     * 字段 -> 字段类型 -> 字段赋值方法
     */
    private static final Function<PaperVO, List<Triple<String, Class<?>, Consumer<Object>>>> MAPPING = entity -> List.of(
            Triple.of("id", Long.class, v -> entity.setId((Long) v)),
            Triple.of("name", String.class, v -> entity.setName((String) v)),
            Triple.of("remark", String.class, v -> entity.setRemark((String) v)),
            Triple.of("start_time", LocalDateTime.class, v -> entity.setStartTime((LocalDateTime) v)),
            Triple.of("end_time", LocalDateTime.class, v -> entity.setEndTime((LocalDateTime) v)),
            Triple.of("duration", Integer.class, v -> entity.setDuration((Integer) v)),
            Triple.of("look_answer", Integer.class, v -> entity.setLookAnswer((Integer) v)),
            Triple.of("upset", Integer.class, v -> entity.setUpset((Integer) v)),
            Triple.of("pass_score", Double.class, v -> entity.setPassScore((Double) v)),
            Triple.of("total_score", Double.class, v -> entity.setTotalScore((Double) v)),
            Triple.of("grade_class_name", String.class, v -> entity.setGradeClassName((String) v)),
            Triple.of("user_score", Double.class, v -> entity.setUserScore((Double) v))
    );

    @Override
    @NonNull
    public PaperVO convert(Row source) {
        RowMetadata meta = source.getMetadata();
        PaperVO entity = new PaperVO();
        MAPPING.apply(entity).forEach(mapping -> {
            if (meta.contains(mapping.getLeft())) {
                mapping.getRight().accept(source.get(mapping.getLeft(), mapping.getMiddle()));
            }
        });
        return entity;
    }
}
